package br.com.nuccitec.jfera.validation.vo;

import java.util.ArrayList;
import java.util.List;

import javax.jdo.PersistenceManager;

import br.com.nuccitec.jfera.jdo.ILoggedUserObject;
import br.com.nuccitec.jfera.jdo.Identifiable;

public abstract class AbstractVO {
	protected IVOColaborator colaborator;
	private String encodedId;

	public String getEncodedId() {
		return encodedId;
	}

	public void setEncodedId(String encodedId) {
		this.encodedId = encodedId;
	}

	public AbstractVO() {
	}

	public AbstractVO(Identifiable identifiable, IVOColaborator colaborator) {
		this.colaborator = colaborator;
		if (identifiable != null)
			copyIdentifiableProperties(identifiable);
	}

	abstract public void copyIdentifiableProperties(Identifiable identifiable);

	public void save() {
		Identifiable objToSave = getRespectiveIdentifiableNewInstance();
		populateIdentifiable(objToSave);
		if (objToSave instanceof ILoggedUserObject) {
			((ILoggedUserObject) objToSave).setUserId(colaborator.getLoggedUser().getId());
		}
		objToSave = colaborator.makePersistent(objToSave);
		copyIdentifiableProperties(objToSave);
	}

	@SuppressWarnings("unchecked")
	public List<AbstractVO> findAll() {
		List<Identifiable> domainList = (List<Identifiable>) colaborator.findAll(getRespectiveIdentifiableNewInstance().getClass());
		List<AbstractVO> voList = new ArrayList<AbstractVO>();
		for (Identifiable i : domainList) {
			AbstractVO vo = getNewInstance();
			vo.setColaborator(colaborator);
			vo.copyIdentifiableProperties(i);
			voList.add(vo);
		}
		return voList;
	}

	@SuppressWarnings("unchecked")
	public List<AbstractVO> findAllFromUser() {
		List<ILoggedUserObject> domainList = (List<ILoggedUserObject>) colaborator.findAllFromUser(getRespectiveIdentifiableNewInstance().getClass());
		List<AbstractVO> voList = new ArrayList<AbstractVO>();
		for (Identifiable i : domainList) {
			AbstractVO vo = getNewInstance();
			vo.setColaborator(colaborator);
			vo.copyIdentifiableProperties(i);
			voList.add(vo);
		}
		return voList;
	}

	public void updateOnDB() {
		PersistenceManager pm =colaborator.getPersistenceManager();
		Identifiable identifiable = pm.getObjectById(getRespectiveIdentifiableNewInstance().getClass(),colaborator.stringToKey(encodedId));
		populateIdentifiable(identifiable);
		pm.close();
	}

	public void deleteFromDB() {
		PersistenceManager pm = colaborator.getPersistenceManager();
		Identifiable objToDelete = (Identifiable) pm.getObjectById(getRespectiveIdentifiableNewInstance().getClass(), colaborator.stringToKey(getEncodedId()));
		pm.deletePersistent(objToDelete);
	}

	abstract public AbstractVO getNewInstance();

	abstract public Identifiable getRespectiveIdentifiableNewInstance();

	abstract public void populateIdentifiable(Identifiable identifiable);

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((encodedId == null) ? 0 : encodedId.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractVO other = (AbstractVO) obj;
		if (encodedId == null) {
			if (other.encodedId != null)
				return false;
		} else if (!encodedId.equals(other.encodedId))
			return false;
		return true;
	}

	public void setColaborator(IVOColaborator colaborator) {
		this.colaborator = colaborator;
	}

	public AbstractVO findByPK() {
		Identifiable i = getRespectiveIdentifiableNewInstance();
		i = colaborator.getObjectById(i.getClass(), getEncodedId());
		copyIdentifiableProperties(i);
		return this;
	}
}
